package com.javaex.book.utils;

import java.io.File;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileItemFactory;
import org.apache.commons.fileupload.FileUploadBase;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.fileupload.servlet.ServletRequestContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 文件上传
 *
 * @author 黄星琦
 * @Date 2022年2月15日
 */
public class UploadUtils {
	
	private static final Logger logger = LoggerFactory.getLogger(UploadUtils.class);
	
	private static final String UPLOAD_DIR = "/upload"; 
	private static final String IMAGE_PATH = "imgPath"; 
	private static final String DEFAULT_IMAGE = "default_image"; 
	
	/**
	 * 对以 multipart/form-data 类型上传的数据进行处理，转为Map
	 * @param req 请求
	 * @return 包含上传表单数据的Map
	 */
	public static Map<String, String> upload(HttpServletRequest req) throws Exception {
		if (!isMultipartContent(req)) {
			throw new RuntimeException("上传的数据不是 multipart/form-data 类型");
		}
		// 创建FileItemFactory工厂实现类
		FileItemFactory fileItemFactory = new DiskFileItemFactory();
		// 创建用于解析上传数据的工具类 ServletFileUpload 的实例
		ServletFileUpload servletFileUpload = new ServletFileUpload(fileItemFactory);
		// 解析上传数据，得到每一个表单项FileItem
		List<FileItem> list = servletFileUpload.parseRequest(req);
		// 遍历每一个表单项， 将List转为Map
		Map<String, String> map = new HashMap<>();
		for (FileItem fileItem : list) {
			// 判断当前表单项是普通表单项，还是上传的文件
			// 普通表单项
			if (fileItem.isFormField()) {	
				map.put(fileItem.getFieldName(), fileItem.getString("UTF-8").trim());
				continue;
			} 
			
			// 文件表单项
			// 如果文件名为空，上传文件为空
			if (fileItem.getName().isEmpty()) {
				continue;
			}
			// 对文件进行重命名
			String extName = fileItem.getName().substring(fileItem.getName().lastIndexOf("."));
			String fileName = UUID.randomUUID().toString().replace("-", "") + extName;
			// 获取文件存放路径，这里是存放到 项目的 webapps/upload 下
			File file = new File(req.getServletContext().getRealPath(UPLOAD_DIR), fileName);
			logger.info("文件写入路径：{}", file.getAbsolutePath());
			fileItem.write(file);	// 写入文件
			map.put(IMAGE_PATH, UPLOAD_DIR + "/" + fileName);
		}
		// 如果未上传文件，只使用原来的文件路径
		if (map.get(IMAGE_PATH) == null || map.get(IMAGE_PATH).isEmpty()) {
			map.put(IMAGE_PATH, map.get(DEFAULT_IMAGE));
		}
		return map;
	}
	
	/**
	 * 自定义isMultipartContent方法，替换`ServletFileUpload.isMultipartContent`方法
	 * @param request 请求
	 * @return 是否是PUT、POST请求，且是否是multipart/form-data数据类型
	 */
	public static final boolean isMultipartContent(HttpServletRequest request) {
        if (RequestMethod.PUT.toString().equalsIgnoreCase(request.getMethod()) 
        		|| RequestMethod.POST.toString().equalsIgnoreCase(request.getMethod())) {
        	return FileUploadBase.isMultipartContent(new ServletRequestContext(request));
        }
        return false;
    }
}
